package com.phiture.erp.finance.core.handler;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import com.phiture.erp.basic.api.pojo.resp.ErpMaterialInfoResp;
import com.phiture.erp.basic.api.service.ErpMaterialApi;
import com.phiture.erp.common.constants.ErpNoPrefixConstants;
import com.phiture.erp.common.utils.ErpNoGenerator;
import com.phiture.erp.finance.common.enums.ErpFinanceStatementStatusEnum;
import com.phiture.erp.finance.core.service.ErpFinanceStatementService;
import com.phiture.erp.finance.dal.entity.ErpFinanceStatementDO;
import com.phiture.erp.finance.dal.entity.ErpFinanceStatementItemsDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.phiture.erp.common.constants.ErrorCodeConstants.*;
import static com.phiture.erp.common.utils.ValidationUtils.validateError;

/**
 * @author YH
 * @date 2025-06-12-8:27
 */

@Slf4j
@Component
public class ErpBaseFinanceStatementHandler {
    @Resource
    private ErpNoGenerator erpNoGenerator;
    @Resource
    private ErpMaterialApi materialApi;
    @Resource
    protected TransactionTemplate transactionTemplate;
    @Resource
    protected ErpFinanceStatementService erpFinanceStatementService;


    protected Pair<LocalDate, LocalDate> periodConvert(String period) {
        validateError(period, s -> !s.matches("\\d{4}-\\d{2}"), FINANCE_STATEMENT_RECONCILIATION_CYCLE_FORMAT_ERROR);
        YearMonth yearMonth = YearMonth.parse(period);
        LocalDate startDate = yearMonth.atDay(1);
        LocalDate endDate = yearMonth.plusMonths(1).atDay(1);
        return Pair.of(startDate, endDate);
    }

    protected ErpFinanceStatementDO toErpFinanceStatementDO(Long supplierId, Integer type, String billingPeriod, BigDecimal totalAmount){
        ErpFinanceStatementDO statementDO = new ErpFinanceStatementDO();
        statementDO.setNo(generateFinanceStatementNo());
        statementDO.setTransactionUserId(supplierId);
        statementDO.setType(type);
        statementDO.setBillingPeriod(billingPeriod);
        statementDO.setStatementDate(LocalDateTime.now());
        statementDO.setTotalAmount(totalAmount);
        statementDO.setTransactionAmount(BigDecimal.ZERO);
        statementDO.setStatus(ErpFinanceStatementStatusEnum.TO_BE_CONFIRMED.getStatus());
        return statementDO;
    }

    protected ErpFinanceStatementItemsDO toErpFinanceStatementItemsDO(Long sourceId, String sourceNo, Long sourceItemId, Long transactionUserId,
                                                                      BigDecimal billingQuantity, BigDecimal price, BigDecimal taxRate,
                                                                      BigDecimal taxAmount, BigDecimal totalAmount, ErpMaterialInfoResp material){
        ErpFinanceStatementItemsDO itemsDO = new ErpFinanceStatementItemsDO();
        itemsDO.setSourceId(sourceId);
        itemsDO.setSourceNo(sourceNo);
        itemsDO.setStatementId(sourceItemId);
        itemsDO.setBillingQuantity(billingQuantity);
        itemsDO.setPrice(price);
        itemsDO.setAmount(price.multiply(billingQuantity));
        itemsDO.setTaxRate(taxRate);
        itemsDO.setTaxAmount(taxAmount);
        itemsDO.setTotalAmount(totalAmount.add(taxAmount));
        itemsDO.setTransactionUserId(transactionUserId);
        if(material != null){
            itemsDO.setMaterialId(material.getId());
            itemsDO.setMaterialName(material.getName());
            itemsDO.setStandard(material.getStandard());
            itemsDO.setUnitId(material.getUnitId());
            itemsDO.setUnitName(material.getUnitName());
        }
        return itemsDO;
    }


    protected Map<Long, ErpMaterialInfoResp> getMaterialMap(Collection<Long> materialIds){
        return materialApi.getMaterialMap(materialIds);
    }

    protected BigDecimal convertPrice(BigDecimal price){
        return price == null ? BigDecimal.ZERO : price;
    }
    
    protected void checkFinanceStatementById(Long id){
        boolean existed = erpFinanceStatementService.existById(id);
        if(!existed){
            throw exception(FINANCE_STATEMENT_NOT_EXISTS);
        }
    }
    
    protected List<ErpFinanceStatementItemsDO> getItemsByFinanceStatementId(Long id){
        List<ErpFinanceStatementItemsDO> items = erpFinanceStatementService.getFinanceStatementItemsListByStatementId(id);
        if(CollUtil.isEmpty(items)){
            log.warn("[ErpBaseFinanceStatementHandler.getItemsByFinanceStatementId] id:{}，未查询到对账单明细", id);
            throw exception(FINANCE_STATEMENT_ITEM_NOT_EXISTS);
        }
        return items;
    }
    
    protected void removeFinanceStatementById(Long id){
        erpFinanceStatementService.removeFinanceStatementById(id);
    }
    
    protected void removeFinanceStatementItemByItemIds(Collection<Long> itemIds){
        erpFinanceStatementService.removeFinanceStatementItemByItemIds(itemIds);
    }

    private String generateFinanceStatementNo(){
        return erpNoGenerator.generate(ErpNoPrefixConstants.FINANCE_STATEMENT_SUPPLIER_NO_PREFIX);
    }
}
